/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.sociesc.findasmartphonespark;

import com.eclipsesource.json.JsonObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sociesc.findasmartphonespark.dao.Dao;
import com.sociesc.findasmartphonespark.model.AccessPoint;
import com.sociesc.findasmartphonespark.model.User;
import com.sociesc.findasmartphonespark.utils.DatabaseUtils;
import com.sociesc.findasmartphonespark.utils.rwJson;
import com.sociesc.findasmartphonespark.wekaUtils.Classificador;
import com.sociesc.findasmartphonespark.wekaUtils.geraArff;
import weka.classifiers.bayes.BayesNet;

import java.io.*;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import static spark.Spark.get;
import static spark.Spark.post;
import static spark.Spark.setPort;
import static spark.SparkBase.setIpAddress;
/**
 *
 * @author Daniel
 */
public class Main {

    static String osName = System.getProperty("os.name");

    /* parametros Weka */
    //pasta onde estão os arquivos txt usados para criar o saida
    static File entrada = null;
    //arquivo arff usado para treinar o classificador
    static String saida = "";
    static String saida2 = "";
    //arquivo arff com as informacoes que deverao ser classificadas
    static String arffClassificar = "";

    // BayesNet é o classificador treinado, chamar Classificador.classificarArff(BayesNet, arrfClassificar)
    // para classificar um conjunto de dados
    static BayesNet BayesNet = new BayesNet();

    static ArrayList<AccessPoint> listaAps = null;

    public static void main(String[] args){
        if (osName.toLowerCase().contains("windows")) {
            entrada = new File("C:\\Users\\DanielArthur\\Desktop\\WifiSignal\\");
            saida = "C:\\Users\\DanielArthur\\Desktop\\saida.arff";
            saida2 = "C:\\Users\\DanielArthur\\Desktop\\saida2.arff";
            arffClassificar = "C:\\Users\\daniel.arthur\\Desktop\\classificar.arff";
        } else {
            entrada = new File(System.getProperty("user.home") + "/weka/WifiSignal/");
            saida = System.getProperty("user.home") + "/weka/saida.arff";
            saida2 = System.getProperty("user.home") + "/weka/saida2.arff";
            arffClassificar = System.getProperty("user.home") + "/weka/classificar.arff";
        }

        String apiPrefix = "api/v1/";
        
        setIpAddress("192.168.1.4");
        //setIpAddress("23.251.156.163");
        setPort(9015);

        /****************************** WEKA     ******************************/
        String retorno = "";
        try {
            retorno = geraArff.iniciar(entrada, saida);
            System.out.println(retorno);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(retorno);
        }

        if (new File(saida).exists()) {
            Logger.getLogger(Main.class.getName()).log(Level.INFO, "Arquivo ARFF encontrado, treinando o classificador...");
            treinaClassificador(saida);
        }
        /****************************** FIM WEKA ******************************/

        get(apiPrefix + "/findUser/:data", (request, response) -> {

            try {
                String json = URLDecoder.decode(request.params(":data"), "UTF-8");

                ArrayList<AccessPoint> aps = rwJson.readJson(json.toString());

                geraArff.geraArffJson(aps, arffClassificar);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            try {
                return Classificador.classificarArff(BayesNet, arffClassificar);
            } catch (IOException e) {
                e.printStackTrace();
                return e;
            }
        });

        /* Recebe lista de access points para treinar o classificador */
        post(apiPrefix + "/recebeSinais/", (request, response) -> {

            String json = request.body();

            System.out.println("JSON: " + json);

            listaAps = rwJson.readJson(json);

            System.out.println("Chegou!" +
                    "\ncontentLength" + request.contentLength() +
                    "\nbody" + request.body() +
                    "\ncontentType" + request.contentType());

            return "Chegou!";
        });

        /* Recebe lista de access points para treinar o classificador */
        post(apiPrefix + "/treina/", (request, response) -> {

            File file = new File(saida2);

            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (listaAps != null) {
                geraArff.geraArffJson2(listaAps, saida2);
                treinaClassificador(saida2);

                System.out.println("Treinado!");
            } else {
                return "Erro, listaAps vazia!";
            }

            return "Treinado!";
        });

        get(apiPrefix + "/hello/:name", (request, response) -> "Hello: " + request.params(":name"));

    }

    public static void treinaClassificador(String saida){
        // BayesNet é o classificado treinado, chamar Classificador.classificarArff(BayesNet, arrfClassificar)
        // para classificar um conjunto de dados
        BayesNet = Classificador.treinar(saida);
    }
}
